package com.nbsaas.boot.data.ext.resource;

import com.nbsaas.boot.data.api.apis.QueryTemplateApi;
import com.nbsaas.boot.data.api.domain.request.QueryTemplateRequest;
import com.nbsaas.boot.data.api.domain.response.QueryTemplateResponse;
import com.nbsaas.boot.data.ext.apis.ResultHandleWork;
import com.nbsaas.boot.data.ext.apis.SqlHandleApi;
import com.nbsaas.boot.data.ext.domain.data.HandleData;
import com.nbsaas.boot.data.ext.domain.request.SqlHandleRequest;
import com.nbsaas.boot.data.ext.handle.ResultDbHandle;
import com.nbsaas.boot.data.utils.FreemarkerUtils;
import com.nbsaas.boot.model.data.mapper.SqlExeMapper;
import com.nbsaas.boot.model.ext.resource.SqlExeResource;
import com.nbsaas.boot.rest.api.SqlExeApi;
import com.nbsaas.boot.rest.request.ResultHandle;
import com.nbsaas.boot.rest.request.ResultHandleObject;
import com.nbsaas.boot.rest.request.SqlObject;
import com.nbsaas.boot.rest.response.ListResponse;
import com.nbsaas.boot.rest.response.MapResponse;
import com.nbsaas.boot.rest.response.PageResponse;
import com.nbsaas.boot.rest.response.ResponseObject;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class SqlHandleResource implements SqlHandleApi {



    private SqlExeApi sqlExeApi;


    @Resource
    private QueryTemplateApi queryTemplateApi;


    @Resource
    private Map<String, ResultHandleWork> resultHandleWorks = new HashMap<>();


    public SqlHandleResource(SqlExeMapper sqlExeMapper) {
        sqlExeApi = new SqlExeResource(sqlExeMapper);
    }

    public ResponseObject<HandleData> getSqlObject(SqlHandleRequest request) {
        ResponseObject<HandleData> result = new ResponseObject<>();
        result.setData(new HandleData());
        try {
            SqlObject obj = new SqlObject();
            Object page = request.getParam().get("page");
            if (page instanceof Long){
                obj.setPage((Long) page);
            }
            Object size = request.getParam().get("size");
            if (size instanceof Long){
                obj.setSize((Long) size);
            }

            String modelKey = request.getModel();

            QueryTemplateRequest req = new QueryTemplateRequest();
            req.setId(modelKey);
            ResponseObject<QueryTemplateResponse> model = queryTemplateApi.view(req);
            if (model.getCode() != 200) {
                result.setCode(501);
                result.setMsg("model不存在");
                return result;
            }
            QueryTemplateResponse query = model.getData();

            obj.setSql(FreemarkerUtils.process(model.getData().getContent(), request.getParam()));
            result.getData().setSqlObject(obj);
            result.getData().setResponse(query);
            result.getData().setParam(request.getParam());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(501);
            result.setMsg("解析json出错");
            return result;
        }
    }


    @Override
    public PageResponse<MapResponse> search(SqlHandleRequest request) {
        PageResponse<MapResponse> result = new PageResponse<>();
        try {
            ResponseObject<HandleData> obj = getSqlObject(request);
            if (obj.getCode() != 200) {
                result.setCode(obj.getCode());
                result.setMsg(obj.getMsg());
                return result;
            }

            result = sqlExeApi.search(obj.getData().getSqlObject());
            handleList(obj, result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(501);
            result.setMsg("解析json出错");
            return result;
        }
    }

    private void handleList(ResponseObject<HandleData> obj, ListResponse<MapResponse> result) {
        //处理结果
        HandleData handleData = obj.getData();
        QueryTemplateResponse response = handleData.getResponse();
        Integer resultHandleType = response.getResultHandleType();
        if (resultHandleType == null) {
            resultHandleType = 2;
        }
        if (resultHandleType == 2) {
            return;
        }
        if (resultHandleType == 1) {
            //如果结合需要再处理
            ResultHandle resultHandleObject = response.getResultHandle();
            if (resultHandleObject.getResultHandleObjects() != null) {

                List<MapResponse> list = result.getData();
                if (list != null) {
                    for (MapResponse mapResponse : list) {
                        for (ResultHandleObject handleObject : resultHandleObject.getResultHandleObjects()) {

                            String handleType = handleObject.getHandleType();
                            if (!StringUtils.hasText(handleType)) {
                                continue;
                            }
                            ResultHandleWork handle = resultHandleWorks.get(handleType);
                            if (handle == null) {
                                continue;
                            }
                            if (handle instanceof ResultDbHandle){
                                ResultDbHandle dbHandle=(ResultDbHandle)handle;
                                dbHandle.setSqlExeApi(sqlExeApi);
                                dbHandle.setQueryTemplateApi(queryTemplateApi);
                            }
                            handle.handle(handleObject,obj.getData().getParam(), mapResponse);

                        }
                    }

                }


            }


        }
    }

    @Override
    public ListResponse<MapResponse> list(SqlHandleRequest request) {
        ListResponse<MapResponse> result = new ListResponse<>();
        try {
            ResponseObject<HandleData> obj = getSqlObject(request);
            if (obj.getCode() != 200) {
                result.setCode(obj.getCode());
                result.setMsg(obj.getMsg());
                return result;
            }
            result = sqlExeApi.list(obj.getData().getSqlObject());
            handleList(obj, result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(501);
            result.setMsg("解析json出错");
            return result;
        }
    }

    @Override
    public ResponseObject<Integer> executeSql(SqlHandleRequest request) {
        ResponseObject<Integer> result = new ResponseObject<Integer>();
        ResponseObject<HandleData> obj = getSqlObject(request);
        if (obj.getCode() != 200) {
            result.setCode(obj.getCode());
            result.setMsg(obj.getMsg());
            return result;
        }

        return sqlExeApi.executeSql(obj.getData().getSqlObject());
    }

    @Override
    public ResponseObject<MapResponse> selectOne(SqlHandleRequest request) {
        ResponseObject<MapResponse> result = new ResponseObject<>();
        ResponseObject<HandleData> obj = getSqlObject(request);
        if (obj.getCode() != 200) {
            result.setCode(obj.getCode());
            result.setMsg(obj.getMsg());
            return result;
        }


        result = sqlExeApi.selectOne(obj.getData().getSqlObject());
        if (result.getData() != null) {
            ListResponse<MapResponse> list = new ListResponse<>();
            list.setData(new ArrayList<>());
            list.getData().add(result.getData());
            handleList(obj, list);
        }
        return result;
    }
}
